//
// Alain Boucher - 19/03/2008
//
// Fonctions utilitaires pour la transformée de Fourier
// TP du cours de Traitement d'images
//
// Note : Les fonctions ci-dessous ne contiennent pas (volontairement)
//        de commentaires dans le code. Les seuls commentaires sont dans 
//        la facon d'utiliser les fonctions. Modifier les parametres et
//        observer les resultats pour bien comprendre le fonctionnement.
//

#include "ImageGray.h"
#include "TPFunctions.h"
#include "ImageRgb.h"
#include "DiskXFile.h"
#include "CmdLine.h"
#include "ipCanny.h"
#include "ipPrewitt.h"
#include "ipKirsch.h"
#include "ipSobel.h"
#include "TPFunctions.h"
#include "xtprobeImageDiskXFile.h"


//******   Detection de filtre *******//

void filtreDetect(Image *image_in,bool verbose,real threshold,char *suffix,int f)
{
	char *name = new char[300];
 	Image *image_out = NULL;

	ipCore *filtre = NULL;

        if(f==3)
        {
            filtre = new ipPrewitt(image_in->width, image_in->height, "gray");
        }
        else if(f==15)
        {
            filtre = new ipKirsch(image_in->width, image_in->height, "gray");
        }
 	
 	filtre->setBOption("verbose", verbose);
 	filtre->setROption("threshold", threshold);
 	filtre->init();
 	filtre->process(image_in);

 	image_out = new ImageGray();
 	image_out->setBOption("verbose", verbose);


	strcpy(name, suffix);
	strcat(name, "gradientx.pgm");
 	image_out->copyFrom(image_in->width, image_in->height, filtre->seq_out->frames[0], "gray");
 	image_out->save(name);

	strcpy(name, suffix);
	strcat(name, "gradienty.pgm");
 	image_out->copyFrom(image_in->width, image_in->height, filtre->seq_out->frames[1], "gray");
 	image_out->save(name);

	strcpy(name, suffix);
	strcat(name, "gradient.pgm");
 	image_out->copyFrom(image_in->width, image_in->height, filtre->seq_out->frames[2], "gray");
 	image_out->save(name);

 	strcpy(name, suffix);
	strcat(name, ".pgm");
 	image_out->copyFrom(image_in->width, image_in->height, filtre->seq_out->frames[3], "gray");
 	image_out->save(name);


 	delete filtre;
 	delete image_out;
}

//******   Detection de Canny *******//

void cannyDetect(Image *image_in,bool verbose,real threshold,char *suffix)
{
	char *name = new char[300];
  	Image *image_out = NULL;

 	ipCore *canny = NULL;

 	canny = new ipCanny(image_in->width, image_in->height, "gray", threshold);
 	canny->setBOption("verbose", verbose);
 	canny->process(image_in);

 	image_out = new ImageGray();
 	image_out->setBOption("verbose", verbose);

	strcpy(name, suffix);
	strcat(name, "gradientxy.pgm");
 	image_out->copyFrom(image_in->width, image_in->height, canny->seq_out->frames[0], "gray");
 	image_out->save(name);

	strcpy(name, suffix);
	strcat(name, "gradient.pgm");
 	image_out->copyFrom(image_in->width, image_in->height, canny->seq_out->frames[1], "gray");
 	image_out->save(name);

	strcpy(name, suffix);
	strcat(name, ".pgm");
  	image_out->copyFrom(image_in->width, image_in->height, canny->seq_out->frames[2], "gray");
 	image_out->save(name);

 	delete canny;
 	delete image_out;

}

//******   Detection de Sobel *******//

void sobelDetect(Image *image_in,bool verbose,real threshold,char *suffix)
{
	char *name = new char[300];  
 	Image *image_out = NULL;

	ipCore *sobel = NULL;

 	sobel = new ipSobel(image_in->width, image_in->height, "gray");
 	sobel->setBOption("verbose", verbose);
 	sobel->setROption("threshold", threshold);
 	sobel->init();
 	sobel->process(image_in);
 	
 	image_out = new ImageGray();
 	image_out->setBOption("verbose", verbose);
 

	strcpy(name, suffix);
	strcat(name, "gradientx.pgm"); 
 	image_out->copyFrom(image_in->width, image_in->height, sobel->seq_out->frames[0], "gray");
 	image_out->save(name);
 
	strcpy(name, suffix);
	strcat(name, "gradienty.pgm"); 
 	image_out->copyFrom(image_in->width, image_in->height, sobel->seq_out->frames[1], "gray");
 	image_out->save(name);
 
	strcpy(name, suffix);
	strcat(name, "gradient.pgm"); 
 	image_out->copyFrom(image_in->width, image_in->height, sobel->seq_out->frames[2], "gray");
 	image_out->save(name);
 
 	strcpy(name, suffix);
	strcat(name, ".pgm"); 
 	image_out->copyFrom(image_in->width, image_in->height, sobel->seq_out->frames[3], "gray");
 	image_out->save(name);

 
 	delete sobel;
 	delete image_out;
}

//******   Chargement de l'image *******//

Image * loadImage(bool verbose,char* image_filename)
{

	Image *source = NULL;
// Création et chargement de l'image
	xtprobeImageDiskXFile *image_file = NULL;
	source = new ImageGray();  	
	source->setBOption("verbose", verbose);

// Choix: xtprobeImageDiskXFile car il permet de travailler avec plusieurs types d'images 

	if(!new xtprobeImageDiskXFile(image_filename, "r"))
            return NULL;

        image_file = new xtprobeImageDiskXFile(image_filename, "r");
	source->loadImageXFile(image_file);
	delete image_file;


	if(verbose)
	{
		print("Image info:\n");
		print("   width = %d\n", source->width);
		print("   height = %d\n", source->height);
		print("   format = %s (%d)\n", source->coding, source->n_planes);
	}

return source;
}

//******   Construction du nom de fichier *******//

char * setTitle(char* string,char* prefix)
{
	
	char *str = new char[300];
	char *str1 = new char[300];
	int i, j=0;
	
// Extraction du nom du fichier sans extension

	for (i = 0; string[i] != '\0'; i ++)
	 {
           if(string[i]!='/')
            {
  	     str[j] = string[i];
             j++;
            }
	   else
            {
	    j=0;
             }             
         }
	str[j ++] = (char)NULL;

	for (i = 0; str[i] != '.'; i ++)
	 {
          str1[i] = str[i];
         }
            
        str1[i] = (char)NULL;	 
 
	strcat(str1, prefix);
	return str1;
}


//******   Calcul du nombre de pixels de couleur color dans l'image *******//

int nbrePixels(Image *image_in,int color)
{
    int nbcol=0;
    for (int line = 0; line < image_in->height; line++)
        for (int i = 0; i < image_in->width; i ++)
        {
	    if(image_in->get(line, i)[0]==color)
                nbcol++;
         }
    return nbcol;
}


//******   Calcul du nombre de pixels commun aux deux images *******//

int nbreCommun(Image *image_ref,Image *image_grad)
{
    int nbcol=0;
    for (int line = 0; line < image_grad->height; line++)
        for (int i = 0; i < image_grad->width; i ++)
        {
	   if(image_grad->get(line, i)[0]==255)
           {
            if((i==0||line==0)||(i==image_grad->width||line==image_grad->height))
            {
             if(pixelBords(image_ref,line, i))
                nbcol++;
            }
            else
            {
             if(pixelVoisins(image_ref,line, i))
                nbcol++;
            }
           }
         }
    return nbcol;
}

//******   Vérification des pixels voisins *******//

bool pixelVoisins(Image *image_in,int line,int i)
{
    for (int k = line-1;  k< line+2; k++)
        for (int j = i-1; j < i+2; j ++)
        {
	    if(image_in->get(k, j)[0]==0)
             return true;
                       
         }
    
    return false;
}

//******   Vérification des pixels de bord *******//

bool pixelBords(Image *image_in,int line,int i)
{

 //Traitement de la première ligne
    
    if(line==0)
    {
      if(i==0)
      {
        if(image_in->get(line, i)[0]==0||image_in->get(line+1, i)[0]==0||image_in->get(line, i+1)[0]==0||image_in->get(line+1, i+1)[0]==0)
           return true;
      }
      if(i==image_in->width)
      {
        if(image_in->get(line, i)[0]==0||image_in->get(line+1, i)[0]==0||image_in->get(line, i-1)[0]==0||image_in->get(line+1, i-1)[0]==0)
           return true;
      }

     for (int k = line;  k< line+2; k++)
        for (int j = i-1; j < i+2; j ++)
        {
	    if(image_in->get(k, j)[0]==0)
             return true;
         }
    }
    
 //Traitement de la première colonne
    if(i==0)
    {
   
      if(line==image_in->height)
      {
        if(image_in->get(line, i)[0]==0||image_in->get(line-1, i)[0]==0||image_in->get(line, i+1)[0]==0||image_in->get(line-1, i+1)[0]==0)
           return true;
      }

     for (int k = line-1;  k< line+2; k++)
        for (int j = i; j < i+2; j ++)
        {
	    if(image_in->get(k, j)[0]==0)
             return true;
         }
    }

  //Traitement de la dernière ligne

    if(line==image_in->height)
    {
      if(i==image_in->width)
      {
        if(image_in->get(line, i)[0]==0||image_in->get(line-1, i)[0]==0||image_in->get(line, i-1)[0]==0||image_in->get(line-1, i-1)[0]==0)
           return true;
      }

     for (int k = line-1;  k< line+1; k++)
        for (int j = i-1; j < i+2; j ++)
        {
	    if(image_in->get(k, j)[0]==0)
             return true;
         }
    }
 
 //Traitement de la dernière colonne

    if(i==image_in->width)
    {
     for (int k = line-1;  k< line+2; k++)
        for (int j = i-1; j < i+1; j ++)
        {
	    if(image_in->get(k, j)[0]==0)
             return true;
         }
    }

    return false;
}

